import { useCallback, useEffect, useState } from 'react';
import { message } from 'antd';
import { AUTH_STORE } from '@/constants';
import {
  resChangeEmail,
  resChangePassword,
  resChangePhone,
  resEmailRegister,
  resLogin,
  resLogout,
  resPhoneLogin,
  resPhoneRegister,
  resResetPassword,
} from '@/services/auth';
import { resetCartStore, useCartStore } from '@/store/cartStore';
import useUserStore from '@/store/userStore';
import { useRequest } from 'ahooks';
import { atom, AtomEffect, selector, useRecoilState } from 'recoil';
import { isValidTokenTime } from '@/utils/auth';
import { local } from '@/utils/storage';

const initAuth: AuthStructure = {
  token: '',
  expire: '',
};

export let resetAuthStore: () => void = () => {};

export const useAuthStore = () => {
  const [auth, setAuth] = useRecoilState(authStore);

  const reset = useCallback(() => {
    setAuth({ token: '', expire: '' });
  }, []);

  const { loading: loginLoading, runAsync: loginRunAsync } = useRequest(
    resLogin,
    { manual: true }
  );
  const login = useCallback((params: API.LoginParams) => {
    return loginRunAsync(params).then(({ token, expire }) => {
      setAuth({ token, expire });
      message.success('登录成功');
      loginAfterAction();
    });
  }, []);

  const { getUserinfo, reset: resetUser } = useUserStore();
  const { loadCart } = useCartStore();

  const loginAfterAction = useCallback(() => {
    getUserinfo();
    loadCart();
  }, []);

  const { loading: phoneLoginLoading, runAsync: phoneLoginRunAsync } =
    useRequest(resPhoneLogin, { manual: true });
  const phoneLogin = useCallback((params: API.LoginPhoneParams) => {
    return phoneLoginRunAsync(params).then(({ code, token, expire }) => {
      setAuth({ token, expire });
      if (code == 201) {
        message.warn(
          '此账号为使用手机号自动创建的新账号，请前往个人中心修改密码！'
        );
      } else {
        message.success('登录成功');
      }
      loginAfterAction();
    });
  }, []);

  const { loading: phoneRegisterLoading, runAsync: phoneRegisterRunAsync } =
    useRequest(resPhoneRegister, { manual: true });
  const phoneRegister = useCallback((params: API.PhoneRegisterParams) => {
    return phoneRegisterRunAsync(params).then(() => {
      message.success('注册成功,请使用手机号作为账户名登录！');
    });
  }, []);

  const { loading: changePhoneLoading, runAsync: changePhoneRunAsync } =
    useRequest(resChangePhone, { manual: true });
  const changePhone = useCallback((params: API.ChangePhoneParams) => {
    return changePhoneRunAsync(params).then(() => {
      message.success('绑定手机成功');
    });
  }, []);

  const { loading: changeEmailLoading, runAsync: changeEmailRunAsync } =
    useRequest(resChangeEmail, { manual: true });
  const changeEmail = useCallback((params: API.ChangeEmailParams) => {
    return changeEmailRunAsync(params).then(() => {
      message.success('绑定邮箱成功');
    });
  }, []);

  const { loading: emailRegisterLoading, runAsync: emailRegisterRunAsync } =
    useRequest(resEmailRegister, { manual: true });
  const emailRegister = useCallback((params: API.EmailRegisterParams) => {
    return emailRegisterRunAsync(params).then(() => {
      message.success('注册成功,请使用邮箱作为账户名登录！');
    });
  }, []);

  const resetPassword = () => {
    const { loading, runAsync } = useRequest(resResetPassword, {
      manual: true,
    });
    const handler = (params: API.ResetPasswordParams) => {
      return runAsync(params).then(() => {
        message.success('重置密码成功，请重新登录!');
      });
    };
    return {
      loading,
      handler,
    };
  };

  const { loading: ChangePwdLoading, runAsync: ChangePwd } = useRequest(
    resChangePassword,
    {
      manual: true,
    }
  );
  const changePwd = useCallback(
    (param: API.ChangePasswordParams) => {
      return ChangePwd(param).then(() => {
        message.success('修改密码成功,请重新登录！');
        logout();
      });
    },
    [ChangePwd]
  );

  const logout = useCallback(() => {
    reset();
    resetUser();
    resetCartStore();
    return resLogout().then(() => {
      message.success('注销登录成功');
    });
  }, []);

  return {
    auth,
    logout,
    login: { login, loading: loginLoading },
    phoneLogin: { phoneLogin, loading: phoneLoginLoading },
    emailRegister: { emailRegister, loading: emailRegisterLoading },
    phoneRegister: { phoneRegister, loading: phoneRegisterLoading },
    changePhone: { changePhone, loading: changePhoneLoading },
    changeEmail: { changeEmail, loading: changeEmailLoading },
    changePwd: { changePwd, loading: ChangePwdLoading },
    resetPassword,
  };
};

const subscriptAuthStore: AtomEffect<AuthStructure> = ({
  onSet,
  setSelf,
  resetSelf,
  trigger,
}) => {
  onSet((newValue) => {
    local.set(AUTH_STORE, newValue);
  });

  if (trigger === 'get') {
    setSelf(local.get<AuthStructure>(AUTH_STORE, initAuth));
  }

  resetAuthStore = () => {
    resetSelf();
  };
};

export const authStore = atom<AuthStructure>({
  key: AUTH_STORE,
  default: initAuth,
  effects_UNSTABLE: [subscriptAuthStore],
});

export const isLoginState = selector({
  key: 'isLogin',
  get: ({ get }) => {
    const { token, expire } = get(authStore);
    return token !== '' && isValidTokenTime(expire);
  },
});
